package com.yunquan.ohana.ui.editPhoto.image

import android.annotation.SuppressLint
import android.content.Intent
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.Color
import android.graphics.Matrix
import android.net.Uri
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.text.Editable
import android.text.TextWatcher
import android.view.View
import android.widget.ImageView
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.view.setPadding
import androidx.recyclerview.widget.LinearLayoutManager
import com.bumptech.glide.Glide
import com.bumptech.glide.load.engine.DiskCacheStrategy
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import com.yalantis.ucrop.UCrop
import com.yunquan.ohana.BR
import com.yunquan.ohana.R
import com.yunquan.ohana.adapter.ModelRecyclerAdapter
import com.yunquan.ohana.adapter.ModelViewHolder
import com.yunquan.ohana.base.bus.RxBus
import com.yunquan.ohana.base.ui.BaseActivity
import com.yunquan.ohana.databinding.ActivityCropImageBinding
import com.yunquan.ohana.entity.EventEntity
import com.yunquan.ohana.entity.EventType
import com.yunquan.ohana.entity.FramesEntity
import com.yunquan.ohana.entity.PhotoResultEntity
import com.yunquan.ohana.entity.UploadRequestEntity
import com.yunquan.ohana.ui.photos.PhotosActivity
import com.yunquan.ohana.utils.FileUtils
import com.yunquan.ohana.utils.L
import com.yunquan.ohana.utils.NetworkUtils
import com.yunquan.ohana.utils.StringUtils
import com.yunquan.ohana.utils.ToastUtils
import com.yunquan.ohana.utils.Utils
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import top.zibin.luban.CompressionPredicate
import top.zibin.luban.Luban
import top.zibin.luban.OnCompressListener
import java.io.File
import java.util.Locale

/**
 * 图片剪辑
 */
class CropImageActivity : BaseActivity<ActivityCropImageBinding, CropImageViewModel>() {

    private val mPhotos = mutableListOf<PhotoResultEntity>()
    private val mFrames = mutableListOf<FramesEntity>()

    private var mImageAdapter: ModelRecyclerAdapter<PhotoResultEntity>? = null

    private var mCurrentPhoto: PhotoResultEntity? = null

    private var mPortrait = false

    private val mContentMap = mutableMapOf<Long, String>()

    override fun initContentView(savedInstanceState: Bundle?): Int {
        return R.layout.activity_crop_image
    }

    override fun initVariableId(): Int {
        return BR.cropImageViewModel
    }

    override fun initParam() {
        super.initParam()
        window.statusBarColor = resources.getColor(R.color.white)
        window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
    }

    @SuppressLint("SetTextI18n")
    override fun initData(savedInstanceState: Bundle?) {
        super.initData(savedInstanceState)
        val screenWidth = Utils.instance.getScreenWidth()
        val screenHeight = Utils.instance.getScreenHeight()
        L.i("宽：${screenWidth},高：${screenHeight}")
        val bundle = intent.extras
        if (bundle != null) {
            val photosJson = bundle.getString("photos")
            val framesJson = bundle.getString("frames")

            val photosType = object : TypeToken<List<PhotoResultEntity>>() {}.type
            val photos: List<PhotoResultEntity> = Gson().fromJson(photosJson, photosType)
            mPhotos.addAll(photos)

            val framesType = object : TypeToken<List<FramesEntity>>() {}.type
            val frames: List<FramesEntity> = Gson().fromJson(framesJson, framesType)
            mFrames.addAll(frames)
        }

        mImageAdapter = ModelRecyclerAdapter(this, mPhotos, R.layout.item_crop_image)
        mImageAdapter?.setBindViewListener(object : ModelRecyclerAdapter.ModelBindViewListener<PhotoResultEntity> {
            override fun onBindView(holder: ModelViewHolder, item: PhotoResultEntity, position: Int) {
                val ivEdit = holder.getViewAtId<ImageView>(R.id.iv_edit)
                val root = holder.getViewAtId<ConstraintLayout>(R.id.cl_root)
                val pic = holder.getViewAtId<ImageView>(R.id.iv_pic)
                val file = if (item.cropPath == null) File(item.path!!) else File(item.cropPath!!)
                Glide.with(holder.getItemView().context).load(file).into(pic)
                if (mCurrentPhoto?.id == item.id) {
                    ivEdit.visibility = View.VISIBLE
                    root.setBackgroundResource(R.drawable.bg_r10_14)
                    root.setPadding(Utils.instance.dp2px(2f))
                } else {
                    ivEdit.visibility = View.INVISIBLE
                    root.setBackgroundColor(Color.TRANSPARENT)
                    root.setPadding(Utils.instance.dp2px(0f))
                }
                ivEdit.setOnClickListener {
                    val oldFileName = item.path!!.substring(item.path.lastIndexOf("/") + 1, item.path.lastIndexOf("."))
                    val fileName = "CROP_${oldFileName}.jpg"
                    val cropFile = File(FileUtils.getFilePath(), fileName)
                    val maxW = if (mPortrait) 800 else 1280
                    val maxH = if (mPortrait) 1280 else 800
                    val scaleW = if (mPortrait) 5f else 8f
                    val scaleH = if (mPortrait) 8f else 5f
                    UCrop.of(Uri.fromFile(File(item.path)), Uri.fromFile(cropFile))
                        .withAspectRatio(scaleW, scaleH)
                        .withMaxResultSize(maxW, maxH)
                        .start(this@CropImageActivity)
                }
                root.setOnClickListener {
                    if (mCurrentPhoto?.id != item.id) {
                        mCurrentPhoto = item
                        val content = mContentMap[item.id]
                        binding!!.etMessage.setText(content ?: "")
                        val showFile = if (mCurrentPhoto!!.cropPath == null) File(mCurrentPhoto!!.path!!) else File(mCurrentPhoto!!.cropPath!!)
                        Glide.with(this@CropImageActivity)
                            .load(showFile)
                            .diskCacheStrategy(DiskCacheStrategy.NONE)
                            .skipMemoryCache(true)
                            .into(binding!!.ivPic)
                        mImageAdapter?.notifyDataSetChanged()
                        mPortrait = (mCurrentPhoto!!.width ?: 0) <= (mCurrentPhoto!!.height ?: 0)
                        setPortrait()
                    }
                }
            }
        })
        binding!!.rvImages.layoutManager = LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false)
        binding!!.rvImages.adapter = mImageAdapter

        binding!!.tvCount.text = "0/100"

        if (mPhotos.isNotEmpty()) {
            mCurrentPhoto = mPhotos[0]
            mPortrait = (mCurrentPhoto!!.width ?: 0) <= (mCurrentPhoto!!.height ?: 0)
            val width = if (mPortrait) 400 else 640
            val height = if (mPortrait) 640 else 400
            Glide.with(this)
                .load(File(mCurrentPhoto!!.path!!))
                .override(width, height)
                .diskCacheStrategy(DiskCacheStrategy.RESOURCE)
                .skipMemoryCache(false)
                .into(binding!!.ivPic)
        } else {
            ToastUtils.showShort("Loading Photo Failed")
        }
        setFramesLayoutParams()
        setPortrait()
    }

    override fun initViewObservable() {
        super.initViewObservable()
        binding!!.etMessage.addTextChangedListener(object : TextWatcher {
            override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}

            @SuppressLint("SetTextI18n")
            override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
                binding!!.tvCount.text = "${s?.length ?: 0}/100"
            }

            override fun afterTextChanged(s: Editable?) {}
        })
        binding!!.llPortrait.setOnClickListener {
            mPortrait = !mPortrait
            if (mPortrait) {
                binding!!.tvPortrait.setText(R.string.portrait)
            } else {
                binding!!.tvPortrait.setText(R.string.landscape)
            }
            setPortrait()
        }
        binding!!.btnSend.setOnClickListener {
            if (!NetworkUtils.isNetworkAvailable()) {
                ToastUtils.showShort(getString(R.string.not_network_available))
                return@setOnClickListener
            }
            if (mPhotos.isEmpty()) {
                ToastUtils.showShort(getString(R.string.no_content_sent))
                return@setOnClickListener
            }
            mPhotos.map { e -> e.content = mContentMap[e.id] }
            compressPhotos()
        }
        binding!!.llFitToFrame.setOnClickListener {
            if (binding!!.ivPic.scaleType == ImageView.ScaleType.CENTER_CROP) {
                binding!!.ivPic.scaleType = ImageView.ScaleType.FIT_CENTER
            } else {
                binding!!.ivPic.scaleType = ImageView.ScaleType.CENTER_CROP
            }
        }
        binding!!.etMessage.addTextChangedListener(object : TextWatcher {
            override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {

            }

            override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
                if (mCurrentPhoto?.id != null) {
                    mContentMap[mCurrentPhoto!!.id!!] = p0.toString()
                }
            }

            override fun afterTextChanged(p0: Editable?) {

            }

        })
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        if (resultCode == RESULT_OK && requestCode == UCrop.REQUEST_CROP) {
            // 裁剪返回
            val resultUri = UCrop.getOutput(data!!)
            mCurrentPhoto?.cropPath = resultUri?.path
            val index = mPhotos.indexOfFirst { it.id == mCurrentPhoto?.id }
            mPhotos[index].cropPath = mCurrentPhoto?.cropPath
            // 更新显示
            val showFile = if (mCurrentPhoto!!.cropPath == null) File(mCurrentPhoto!!.path!!) else File(mCurrentPhoto!!.cropPath!!)
            Glide.with(this@CropImageActivity)
                .load(showFile)
                .diskCacheStrategy(DiskCacheStrategy.NONE)
                .skipMemoryCache(true)
                .into(binding!!.ivPic)
            mImageAdapter?.notifyDataSetChanged()
        } else if (requestCode == UCrop.RESULT_ERROR) {
            val cropError = UCrop.getError(data!!)
            L.e("裁剪报错->\n${cropError?.message}")
        }
    }

    private fun setFramesLayoutParams() {
        val sw = Utils.instance.getScreenWidth() // 1080
        val dw = 375f / 246f
        val dh = 375f / 168.75f
        val cw = 375f / 206f
        val ch = 375f / 128.75f
        mFramesKW = (sw / dw).toInt()
        mFramesKH = (sw / dh).toInt()
        mFramesTW = (sw / cw).toInt()
        mFramesTH = (sw / ch).toInt()
        // 计算相框显示高度
        val kw = 375f / 252f
        val kh = (sw / kw).toInt()
        val params = binding!!.rlFrames.layoutParams
        params.height = kh
        binding!!.rlFrames.layoutParams = params
        // 获得相册边框
        mBitmap1 = BitmapFactory.decodeResource(resources, R.mipmap.ic_frames)
        val matrix = Matrix()
        matrix.postRotate(90f)
        mBitmap2 = Bitmap.createBitmap(mBitmap1, 0, 0, mBitmap1.width, mBitmap1.height, matrix, true)
    }

    // 横向边框
    private lateinit var mBitmap1: Bitmap

    // 竖向边框
    private lateinit var mBitmap2: Bitmap

    private var mFramesKW: Int = 0
    private var mFramesKH: Int = 0
    private var mFramesTW: Int = 0
    private var mFramesTH: Int = 0

    private fun setPortrait() {
        val backgroundParams = binding!!.ivBackground.layoutParams
        val params = binding!!.ivPic.layoutParams
        if (mPortrait) {
            backgroundParams.width = mFramesKH
            backgroundParams.height = mFramesKW
            params.width = mFramesTH
            params.height = mFramesTW
            binding!!.ivBackground.setImageBitmap(mBitmap2)
        } else {
            backgroundParams.width = mFramesKW
            backgroundParams.height = mFramesKH
            params.width = mFramesTW
            params.height = mFramesTH
            binding!!.ivBackground.setImageBitmap(mBitmap1)
        }

        binding!!.ivBackground.layoutParams = backgroundParams
        binding!!.ivPic.layoutParams = params
    }

    /**
     * 压缩图片
     */
    private fun compressPhotos() {
        showLoading()
        GlobalScope.launch(Dispatchers.IO) {
            for (e in mPhotos) {
                try {
                    val path = e.cropPath ?: e.path
                    val files = Luban.with(this@CropImageActivity)
                        .ignoreBy(1024 * 1024)
                        .load(path).get()
                    if (files.isNotEmpty()) {
                        e.cropPath = files.first().absolutePath
                    }
                } catch (e: Exception) {
                    L.e("Luban 压缩报错", e)
                }
            }
            val bean = UploadRequestEntity(
                type = 1,
                photos = mPhotos,
                frames = mFrames,
            )
            withContext(Dispatchers.Main) {
                dismissLoading()
                RxBus.getDefault().post(EventEntity(EventType.SEND_TO_FRAMES, bean))
                Handler(Looper.getMainLooper()).postDelayed({
                    setResult(PhotosActivity.EDIT_RESULT_CODE)
                    finish()
                }, 300)
            }
        }
    }
}